home *** CD-ROM | disk | FTP | other *** search
- Subject: v12i035: C News alpha release, Part10/14
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rs@uunet.UU.NET
-
- Submitted-by: utzoo!henry (Henry Spencer)
- Posting-number: Volume 12, Issue 35
- Archive-name: cnews/part10
-
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 10 (of 14)."
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'rna/funcs.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'rna/funcs.c'\"
- else
- echo shar: Extracting \"'rna/funcs.c'\" \(9767 characters\)
- sed "s/^X//" >'rna/funcs.c' <<'END_OF_FILE'
- X#include "defs.h"
- X
- X/*
- X * string handling functions
- X */
- Xchar *
- Xmyalloc(size)
- Xint size;
- X{
- X register char *cp;
- X
- X extern char *malloc();
- X
- X if ((cp = malloc((unsigned) size)) == NIL(char))
- X error("No more memory.");
- X return cp;
- X}
- X
- X
- Xchar *
- Xmyrealloc(ptr, size)
- Xchar *ptr;
- Xint size;
- X{
- X register char *cp;
- X
- X extern char *realloc();
- X
- X if ((cp = realloc(ptr, (unsigned) size)) == NIL(char))
- X error("No more memory.");
- X return cp;
- X}
- X
- X
- Xchar *
- Xnewstr(s)
- Xchar *s;
- X{
- X return strcpy(myalloc(strlen(s) + 1), s);
- X}
- X
- X
- Xchar *
- Xnewstr2(s1, s2)
- Xchar *s1, *s2;
- X{
- X return strcat(strcpy(myalloc(strlen(s1) + strlen(s2) + 1), s1), s2);
- X}
- X
- X
- Xchar *
- Xnewstr3(s1, s2, s3)
- Xchar *s1, *s2, *s3;
- X{
- X return strcat(strcat(strcpy(myalloc(strlen(s1) + strlen(s2) + strlen(s3) +
- X 1), s1), s2), s3);
- X}
- X
- X
- Xchar *
- Xnewstr4(s1, s2, s3, s4)
- Xchar *s1, *s2, *s3, *s4;
- X{
- X return strcat(strcat(strcat(strcpy(myalloc(strlen(s1) + strlen(s2) +
- X strlen(s3) + strlen(s4) + 1), s1), s2), s3), s4);
- X}
- X
- X
- Xchar *
- Xnewstr5(s1, s2, s3, s4, s5)
- Xchar *s1, *s2, *s3, *s4, *s5;
- X{
- X return strcat(strcat(strcat(strcat(strcpy(myalloc(strlen(s1) + strlen(s2) +
- X strlen(s3) + strlen(s4) + strlen(s5) + 1), s1), s2), s3), s4), s5);
- X}
- X
- X
- Xchar *
- Xnewstr6(s1, s2, s3, s4, s5, s6)
- Xchar *s1, *s2, *s3, *s4, *s5, *s6;
- X{
- X return strcat(strcat(strcat(strcat(strcat(strcpy(myalloc(strlen(s1) +
- X strlen(s2) + strlen(s3) + strlen(s4) + strlen(s5) + strlen(s6) + 1),
- X s1), s2), s3), s4), s5), s6);
- X}
- X
- X
- Xchar *
- Xcatstr(old, s)
- Xchar *old, *s;
- X{
- X return strcat(myrealloc(old, strlen(old) + strlen(s) + 1), s);
- X}
- X
- X
- Xchar *
- Xcatstr2(old, s1, s2)
- Xchar *old, *s1, *s2;
- X{
- X return strcat(strcat(myrealloc(old, strlen(old) + strlen(s1) + strlen(s2) +
- X 1), s1), s2);
- X}
- X
- X
- X/*
- X * News group matching.
- X *
- X * nglist is a list of newsgroups.
- X * sublist is a list of subscriptions.
- X * sublist may have "meta newsgroups" in it.
- X * All fields are NGSEPCHAR separated.
- X *
- X * sublist uses "all" like shell uses "*", and "." like shell uses "/"
- X * if subscription X matches Y, it also matches Y.anything
- X */
- Xngmatch(nglist, sublist)
- Xchar *nglist, *sublist;
- X{
- X register char *n, *s, *nd, *sd;
- X register int rc;
- X
- X rc = 0;
- X n = nglist;
- X while (*n && rc == 0) {
- X if (nd = strchr(n, NGSEPCHAR))
- X *nd = '\0';
- X s = sublist;
- X while (*s) {
- X if (sd = strchr(s, NGSEPCHAR))
- X *sd = '\0';
- X if (*s != NEGCHAR)
- X rc |= ptrncmp(s, n);
- X else
- X rc &= ~ptrncmp(s + 1, n);
- X if (sd)
- X *sd = NGSEPCHAR, s = sd + 1;
- X else
- X break;
- X }
- X if (nd)
- X *nd = NGSEPCHAR, n = nd + 1;
- X else
- X break;
- X }
- X return rc;
- X}
- X
- X
- X/*
- X * Compare two newsgroups for equality.
- X * The first one may be a "meta" newsgroup.
- X */
- Xstatic
- Xptrncmp(ng1, ng2)
- Xregister char *ng1, *ng2;
- X{
- X
- X while (1) {
- X if (ng1[0] == 'a' && ng1[1] == 'l' && ng1[2] == 'l' && (ng1[3] ==
- X '\0' || ng1[3] == '.')) {
- X if (ng1[3] == '\0') /* "all" matches anything */
- X return 1;
- X while (*ng2 && *ng2 != '.')
- X ng2++;
- X if (*ng2 != '.') /* "all." doesn't match "xx" */
- X return 0;
- X ng1 += 4, ng2++;
- X continue;
- X }
- X while (*ng1 && *ng1 != '.' && *ng1 == *ng2)
- X ng1++, ng2++;
- X if (*ng1 == '.') {
- X if (*ng2 != '.' && *ng2 != '\0')
- X return 0; /* "."'s don't line up */
- X if (*ng2)
- X ng2++;
- X ng1++; /* "."'s line up - keep going */
- X } else if (*ng1 == '\0')
- X return (*ng2 == '\0' || *ng2 == '.');
- X /* full match or X matching X.thing */
- X else
- X return 0;
- X }
- X /* NOTREACHED */
- X}
- X
- X
- X/*
- X * return new newsgroup composed of only those from 'nglist'
- X * subscribed to by 'sublist'
- X * return NULL for empty list
- X */
- Xchar *
- Xngsquash(nglist, sublist)
- Xregister char *nglist, *sublist;
- X{
- X register char *delim;
- X register char *newg;
- X
- X newg = NIL(char);
- X while (*nglist) {
- X if (delim = strchr(nglist, NGSEPCHAR))
- X *delim = '\0';
- X if (ngmatch(nglist, sublist))
- X newg = (newg ? catstr2(newg, NGSEPS, nglist) : newstr(nglist));
- X if (delim)
- X *delim = NGSEPCHAR, nglist = delim + 1;
- X else
- X break;
- X }
- X return newg;
- X}
- X
- X
- X/*
- X * get unique sequence number from SEQ
- X */
- Xchar *
- Xgetunique()
- X{
- X register long number;
- X register FILE *f;
- X static char buf[12];
- X
- X f = fopenl(SEQ);
- X if (fread(buf, 1, sizeof(buf), f) > 0)
- X number = atol(buf);
- X else
- X number = 1;
- X
- X rewind(f);
- X (void) fprintf(f, "%ld\n", number + 1);
- X fclose(f);
- X#if !AUSAM
- X unlock(SEQ);
- X#endif
- X
- X sprintf(buf, "%ld", number);
- X return buf;
- X}
- X
- X
- X/*
- X * open a locked file (or create) for reading and writing
- X */
- XFILE *
- Xfopenl(fname)
- Xchar *fname;
- X{
- X register FILE *f;
- X#ifdef AUSAM
- X struct stat sbuf;
- X#endif
- X
- X extern uid_t newsuid;
- X
- X if ((f = fopen(fname, "r+")) == NIL(FILE) && (f = fopen(fname, "w+")) ==
- X NIL(FILE))
- X error("Can't open %s", fname);
- X
- X#if AUSAM
- X if (fstat(fileno(f), &sbuf) != 0)
- X error("Can't stat %s", fname);
- X if ((sbuf.st_mode & S_IFMT) != S_IFALK && (chmod(fname, (int) (sbuf.st_mode
- X &~S_IFMT) | S_IFALK) != 0 || chown(fname, (int) newsuid, (int) newsuid) !=
- X 0 || fclose(f) == EOF || (f = fopen(fname, "r+")) == NIL(FILE)))
- X error("Can't create %s", fname);
- X#else
- X chown(fname, (int) newsuid, (int) newsuid);
- X lock(fname);
- X#endif
- X
- X return f;
- X}
- X
- X
- X#if !AUSAM
- X
- X#define LSUFFIX ".lock" /* suffix for lock files */
- X
- Xlock(fname)
- Xchar *fname;
- X{
- X register char *lname;
- X register int i, f;
- X
- X lname = newstr2(fname, LSUFFIX);
- X for (i = 0; i < 10; i++) {
- X if ((f = creat(lname, 0)) != -1) {
- X close(f);
- X free(lname);
- X return;
- X }
- X sleep(2);
- X }
- X error("Can't creat %s after %d tries", lname, i);
- X}
- X
- X
- Xunlock(fname)
- Xchar *fname;
- X{
- X register char *lname;
- X
- X lname = newstr2(fname, LSUFFIX);
- X unlink(lname);
- X free(lname);
- X}
- X
- X
- X#endif
- X
- X/*
- X * open a file
- X */
- XFILE *
- Xfopenf(name, mode)
- Xchar *name, *mode;
- X{
- X register FILE *f;
- X
- X if ((f = fopen(name, mode)) == NIL(FILE))
- X error("Can't %s %s", *mode == 'r' ? "open" : "create", name);
- X return f;
- X}
- X
- X
- X/*
- X * replace all '.''s with '/'
- X */
- Xchar *
- Xconvg(s)
- Xregister char *s;
- X{
- X register char *sav;
- X
- X sav = s;
- X while (s = strchr(s, '.'))
- X *s = '/';
- X return sav;
- X}
- X
- X
- X/*
- X * replace all '/''s with '.'
- X */
- Xchar *
- Xrconvg(s)
- Xregister char *s;
- X{
- X register char *sav;
- X
- X sav = s;
- X while (s = strchr(s, '/'))
- X *s = '.';
- X return sav;
- X}
- X
- X
- X/*
- X * get a line from stdin
- X * trim leading and trailing blanks
- X */
- Xchar *
- Xmgets()
- X{
- X register char *s;
- X static char buf[BUFSIZ];
- X
- X fflush(stdout);
- X if (fgets(buf, sizeof(buf), stdin) == NIL(char)) {
- X (void) printf("\n");
- X return NIL(char);
- X }
- X if (s = strchr(buf, '\n'))
- X while (isspace(*s) && s > buf)
- X *s-- = '\0';
- X else
- X {
- X (void) printf("Input line too long.\n");
- X return NIL(char);
- X }
- X s = buf;
- X while (isspace(*s))
- X s++;
- X return s;
- X}
- X
- X
- Xreadln(f)
- XFILE *f;
- X{
- X register int c;
- X
- X if (feof(f) || ferror(f))
- X return;
- X while ((c = getc(f)) != '\n' && c != EOF)
- X ;
- X}
- X
- X
- X/*
- X * compare string pointers
- X */
- Xstrpcmp(a, b)
- Xchar **a, **b;
- X{
- X return CMP(*a, *b);
- X}
- X
- X
- X/*
- X * apply the given function to each member in the newsgroup
- X */
- X/* VARARGS2 */
- Xapplyng(ng, func, arg1)
- Xregister char *ng;
- Xregister int (*func)();
- Xchar *arg1;
- X{
- X register char *delim;
- X register int err;
- X
- X err = 0;
- X while (*ng) {
- X if (delim = strchr(ng, NGSEPCHAR))
- X *delim = '\0';
- X err += (*func)(ng, arg1);
- X if (delim)
- X *delim = NGSEPCHAR, ng = delim + 1;
- X else
- X break;
- X }
- X return err;
- X}
- X
- X
- X/*
- X * generate a return address
- X */
- Xchar *
- Xgetretaddr(hp)
- Xheader *hp;
- X{
- X register char *ra;
- X
- X extern char *getpath(), *exaddress();
- X#ifdef NETPATH
- X extern char *getnetpath();
- X#endif
- X
- X if (hp->h_replyto)
- X ra = exaddress(hp->h_replyto);
- X else if (hp->h_from)
- X ra = exaddress(hp->h_from);
- X else
- X ra = NIL(char);
- X if (hp->h_path && !ra)
- X ra = getpath(hp->h_path);
- X#ifdef NETPATH
- X if (CMPN(ra, PATHPREF, sizeof(PATHPREF) - 1) == 0)
- X ra = getnetpath(ra);
- X#endif
- X return ra;
- X}
- X
- X
- X/*
- X * try and make a proper address
- X */
- Xchar *
- Xexaddress(addr)
- Xchar *addr;
- X{
- X register char *space, *dot, *at;
- X register char *raddr;
- X
- X raddr = NIL(char);
- X if (space = strchr(addr, ' '))
- X *space = '\0';
- X if (at = strchr(addr, '@')) {
- X *at = '\0';
- X if (dot = strchr(at + 1, '.')) {
- X *dot = '\0';
- X#if OZ
- X if (CMP(dot + 1, MYDOMAIN) == 0)
- X raddr = newstr3(addr, ":", at + 1);
- X else
- X#endif
- X raddr = newstr4(PATHPREF, at + 1, PSEPS, addr);
- X *dot = '.';
- X }
- X *at = '@';
- X }
- X if (space)
- X *space = ' ';
- X return raddr;
- X
- X}
- X
- X
- X/*
- X * return the last two components of the path
- X */
- Xchar *
- Xgetpath(path)
- Xchar *path;
- X{
- X register char *exlast, *ex;
- X register char *raddr;
- X
- X if (exlast = strrchr(path, PSEPCHAR)) {
- X *exlast = '\0';
- X if (ex = strrchr(path, PSEPCHAR))
- X raddr = newstr4(PATHPREF, ex + 1, PSEPS, exlast + 1);
- X else
- X raddr = newstr3(path, PSEPS, exlast + 1);
- X *exlast = PSEPCHAR;
- X } else
- X raddr = NIL(char);
- X return raddr;
- X}
- X
- X
- X#ifdef NETPATH
- X/*
- X * try and work out a path from our "netpath" database
- X */
- Xchar *
- Xgetnetpath(path)
- Xchar *path;
- X{
- X FILE * f;
- X register char *ex1, *ex2, *com, *new;
- X char buf[BUFSIZ];
- X
- X if ((ex1 = strchr(path, PSEPCHAR)) && (ex2 = strchr(ex1 + 1, PSEPCHAR))) {
- X *ex2 = '\0';
- X com = newstr4("exec ", NETPATH, " mulga ", ex1 + 1);
- X if ((f = popen(com, "r")) == NIL(FILE))
- X (void) printf("Couldn't run \"%s\"\n", com);
- X else
- X {
- X fread(buf, sizeof(buf), 1, f);
- X if (pclose(f) != 0) {
- X (void) printf("Error in running \"%s\"\n", com);
- X fflush(stdout);
- X } else if (CMPN(buf, "mulga!", 6) == 0) {
- X if (ex1 = strchr(buf, '\n'))
- X *ex1 = '\0';
- X new = newstr4(buf + 6, PSEPS, ex2 + 1, ":mulga");
- X free(path);
- X path = new;
- X }
- X }
- X free(com);
- X *ex2 = PSEPCHAR;
- X }
- X return path;
- X
- X}
- X
- X
- X#endif
- X
- X/*
- X * remove extra spaces, and insert separators if necessary in
- X * newsgroups specification
- X */
- Xconvgrps(sp)
- Xregister char *sp;
- X{
- X register char *sep;
- X
- X sep = NIL(char);
- X while (*sp) {
- X if (sep)
- X sp++;
- X while (*sp && (isspace(*sp) || *sp == NGSEPCHAR))
- X strcpy(sp, sp + 1);
- X if (sep)
- X *sep = (*sp ? NGSEPCHAR : '\0');
- X while (*sp && !isspace(*sp) && *sp != NGSEPCHAR)
- X sp++;
- X sep = sp;
- X }
- X}
- X
- X
- END_OF_FILE
- if test 9767 -ne `wc -c <'rna/funcs.c'`; then
- echo shar: \"'rna/funcs.c'\" unpacked with wrong size!
- fi
- # end of 'rna/funcs.c'
- fi
- if test -f 'rna/header.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'rna/header.c'\"
- else
- echo shar: Extracting \"'rna/header.c'\" \(10079 characters\)
- sed "s/^X//" >'rna/header.c' <<'END_OF_FILE'
- X/*
- X * extract/output headers
- X */
- X
- X#include "defs.h"
- X
- X#if AUSAM
- Xextern struct pwent pe;
- X#else
- Xextern struct passwd *pp;
- X#endif
- Xextern char systemid[];
- Xextern long now;
- X
- Xchar tzone[] = TIMEZONE;
- Xchar hform[] = "%s: %s\n";
- X
- X/* Mandatory Headers */
- Xchar t_relayversion[] = "Relay-Version";
- Xchar t_postversion[] = "Posting-Version";
- Xchar t_from[] = "From";
- Xchar t_date[] = "Date";
- Xchar t_newsgroups[] = "Newsgroups";
- Xchar t_subject[] = "Subject";
- Xchar t_messageid[] = "Message-ID";
- Xchar t_path[] = "Path";
- X
- X/* Optional Headers */
- Xchar t_replyto[] = "Reply-To";
- Xchar t_sender[] = "Sender";
- Xchar t_followupto[] = "Followup-To";
- Xchar t_datereceived[] = "Date-Received";
- Xchar t_expires[] = "Expires";
- Xchar t_references[] = "References";
- Xchar t_control[] = "Control";
- Xchar t_distribution[] = "Distribution";
- Xchar t_organization[] = "Organization";
- Xchar t_lines[] = "Lines";
- X
- Xtypedef enum ft
- X{
- X f_control, f_date, f_datereceived, f_distribution,
- X f_expires, f_followupto, f_from, f_lines, f_messageid,
- X f_newsgroups, f_organization, f_path, f_postversion,
- X f_references, f_relayversion, f_replyto, f_sender,
- X f_subject
- X}
- X
- X
- Xftype;
- X
- Xtypedef struct field {
- X char *f_name;
- X ftype f_type;
- X} field;
- X
- Xstatic field fields[] =
- X{
- X { t_control, f_control },
- X { t_date, f_date },
- X { t_datereceived, f_datereceived },
- X { t_distribution, f_distribution },
- X { t_expires, f_expires },
- X { t_followupto, f_followupto },
- X { t_from, f_from },
- X { t_lines, f_lines },
- X { t_messageid, f_messageid },
- X { t_newsgroups, f_newsgroups },
- X { t_organization, f_organization },
- X { t_path, f_path },
- X { t_postversion, f_postversion },
- X { t_references, f_references },
- X { t_relayversion, f_relayversion },
- X { t_replyto, f_replyto },
- X { t_sender, f_sender },
- X { t_subject, f_subject }
- X};
- X
- X
- Xchar *weekdays[7] =
- X{
- X "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
- X};
- X
- X
- Xchar *months[12] =
- X{
- X "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- X "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
- X};
- X
- X
- Xstatic
- Xfieldcmp(a, b)
- Xfield *a, *b;
- X{
- X return CMP(a->f_name, b->f_name);
- X}
- X
- X
- X/*
- X * extract headers from file,
- X * position file to start of body
- X */
- Xgethead(f, hp)
- XFILE *f;
- Xheader *hp;
- X{
- X register char *colon, *space, *s;
- X register field *fp;
- X field af;
- X char buf[BUFLEN*2];
- X
- X char *hfgets();
- X
- X memset((char *) hp, 0, sizeof(header));
- X while (hfgets(buf, sizeof(buf), f)) {
- X if (buf[0] == '\n')
- X return;
- X if (isupper(buf[0]) && (colon = strchr(buf, ':')) && (space =
- X strchr(buf, ' ')) && (colon + 1 == space)) {
- X *colon = '\0';
- X af.f_name = buf;
- X fp = (field * ) bsearch((char *) & af, (char *) fields,
- X sizeof(fields) / sizeof(fields[0]), sizeof(fields[0]),
- X fieldcmp);
- X *colon = ':';
- X } else
- X fp = NIL(field);
- X if (!fp)
- X if (hp->h_others)
- X hp->h_others = catstr(hp->h_others, buf);
- X else
- X hp->h_others = newstr(buf);
- X else
- X {
- X if (colon = strchr(space + 1, '\n'))
- X *colon = '\0';
- X s = newstr(space + 1);
- X switch (fp->f_type) {
- X case f_control:
- X hp->h_control = s;
- X break;
- X case f_date:
- X hp->h_date = s;
- X break;
- X case f_datereceived:
- X hp->h_datereceived = s;
- X break;
- X case f_distribution:
- X hp->h_distribution = s;
- X break;
- X case f_expires:
- X hp->h_expires = s;
- X break;
- X case f_followupto:
- X hp->h_followupto = s;
- X break;
- X case f_from:
- X hp->h_from = s;
- X break;
- X case f_lines:
- X hp->h_lines = s;
- X break;
- X case f_messageid:
- X hp->h_messageid = s;
- X break;
- X case f_newsgroups:
- X hp->h_newsgroups = s;
- X break;
- X case f_organization:
- X hp->h_organisation = s;
- X break;
- X case f_path:
- X hp->h_path = s;
- X break;
- X case f_postversion:
- X hp->h_postversion = s;
- X break;
- X case f_references:
- X hp->h_references = s;
- X break;
- X case f_relayversion:
- X hp->h_relayversion = s;
- X break;
- X case f_replyto:
- X hp->h_replyto = s;
- X break;
- X case f_sender:
- X hp->h_sender = s;
- X break;
- X case f_subject:
- X hp->h_subject = s;
- X break;
- X }
- X }
- X }
- X}
- X
- X
- X/*
- X * put headers to file
- X */
- Xputhead(hp, f, com)
- Xheader *hp;
- XFILE *f;
- Xpheadcom com;
- X{
- X register char *s;
- X char *getunique();
- X extern char *getenv();
- X
- X if (hp->h_relayversion && com == printing)
- X (void) fprintf(f, hform, t_relayversion, hp->h_relayversion);
- X else if (com != printing)
- X (void) fprintf(f, "%s: version %s; site %s.%s\n", t_relayversion, NEWSVERSION,
- X systemid, MYDOMAIN);
- X
- X if (hp->h_postversion)
- X (void) fprintf(f, hform, t_postversion, hp->h_postversion);
- X else if (com == making)
- X (void) fprintf(f, "%s: version %s; site %s.%s\n", t_postversion, NEWSVERSION,
- X systemid, MYDOMAIN);
- X
- X
- X if (hp->h_from)
- X (void) fprintf(f, hform, t_from, hp->h_from);
- X else if(com == making) {
- X if(s = getenv("NAME"))
- X (void) fprintf(f, "%s: %s@%s.%s (%s)\n", t_from,
- X#if AUSAM
- X pe.pw_strings[LNAME],
- X#else
- X pp->pw_name,
- X#endif
- X systemid, MYDOMAIN, s);
- X else
- X (void) fprintf(f,
- X#if AUSAM
- X "%s: %s@%s.%s (%s %s)\n",
- X#else
- X "%s: %s@%s.%s\n",
- X#endif
- X t_from,
- X#if AUSAM
- X pe.pw_strings[LNAME],
- X#else
- X pp->pw_name,
- X#endif
- X systemid, MYDOMAIN
- X#if AUSAM
- X ,
- X pe.pw_strings[FIRSTNAME],
- X pe.pw_strings[LASTNAME]
- X#endif
- X );
- X }
- X
- X if (hp->h_date)
- X (void) fprintf(f, hform, t_date, hp->h_date);
- X else if (com == making)
- X (void) fprintf(f, hform, t_date, ttoa(now));
- X
- X if (hp->h_newsgroups)
- X (void) fprintf(f, hform, t_newsgroups, hp->h_newsgroups);
- X else if (com == making)
- X (void) fprintf(f, hform, t_newsgroups, DFLTGRP);
- X
- X if (hp->h_subject)
- X (void) fprintf(f, hform, t_subject, hp->h_subject);
- X else if (com == making)
- X error("No subject field.");
- X
- X if (hp->h_messageid)
- X (void) fprintf(f, hform, t_messageid, hp->h_messageid);
- X else if (com == making)
- X error("No messageid.");
- X
- X if (hp->h_path && com == passing)
- X (void) fprintf(f, "%s: %s!%s\n", t_path, systemid, hp->h_path);
- X else if (hp->h_path)
- X (void) fprintf(f, hform, t_path, hp->h_path);
- X else if(com == making)
- X (void) fprintf(f, "%s: %s!%s\n", t_path, systemid,
- X#if AUSAM
- X pe.pw_strings[LNAME]
- X#else
- X pp->pw_name
- X#endif
- X );
- X
- X /* optional */
- X
- X if (hp->h_replyto)
- X (void) fprintf(f, hform, t_replyto, hp->h_replyto);
- X
- X if (hp->h_sender)
- X (void) fprintf(f, hform, t_sender, hp->h_sender);
- X
- X if (hp->h_followupto)
- X (void) fprintf(f, hform, t_followupto, hp->h_followupto);
- X
- X if (hp->h_datereceived && com == printing)
- X (void) fprintf(f, hform, t_datereceived, hp->h_datereceived);
- X else if (com != printing)
- X (void) fprintf(f, hform, t_datereceived, ttoa(now));
- X
- X if (hp->h_expires)
- X (void) fprintf(f, hform, t_expires, hp->h_expires);
- X
- X if (hp->h_references)
- X (void) fprintf(f, hform, t_references, hp->h_references);
- X
- X if (hp->h_control)
- X (void) fprintf(f, hform, t_control, hp->h_control);
- X
- X if (hp->h_distribution)
- X (void) fprintf(f, hform, t_distribution, hp->h_distribution);
- X
- X if (hp->h_organisation)
- X (void) fprintf(f, hform, t_organization, hp->h_organisation);
- X else if (com == making)
- X (void) fprintf(f, hform, t_organization, (s = getenv("ORGANIZATION")) ?
- X s : MYORG);
- X
- X if (hp->h_lines)
- X (void) fprintf(f, hform, t_lines, hp->h_lines);
- X
- X if (hp->h_others)
- X fputs(hp->h_others, f);
- X}
- X
- X
- X/*
- X * free all strings allocated to header
- X */
- Xfreehead(hp)
- Xregister header *hp;
- X{
- X if (hp->h_relayversion)
- X free(hp->h_relayversion);
- X if (hp->h_postversion)
- X free(hp->h_postversion);
- X if (hp->h_from)
- X free(hp->h_from);
- X if (hp->h_date)
- X free(hp->h_date);
- X if (hp->h_newsgroups)
- X free(hp->h_newsgroups);
- X if (hp->h_subject)
- X free(hp->h_subject);
- X if (hp->h_messageid)
- X free(hp->h_messageid);
- X if (hp->h_path)
- X free(hp->h_path);
- X if (hp->h_replyto)
- X free(hp->h_replyto);
- X if (hp->h_sender)
- X free(hp->h_sender);
- X if (hp->h_followupto)
- X free(hp->h_followupto);
- X if (hp->h_datereceived)
- X free(hp->h_datereceived);
- X if (hp->h_expires)
- X free(hp->h_expires);
- X if (hp->h_references)
- X free(hp->h_references);
- X if (hp->h_control)
- X free(hp->h_control);
- X if (hp->h_distribution)
- X free(hp->h_distribution);
- X if (hp->h_organisation)
- X free(hp->h_organisation);
- X if (hp->h_lines)
- X free(hp->h_lines);
- X if (hp->h_others)
- X free(hp->h_others);
- X}
- X
- X
- X/*
- X * hfgets is like fgets, but deals with continuation lines.
- X * It also ensures that even if a line that is too long is
- X * received, the remainder of the line is thrown away
- X * instead of treated like a second line.
- X */
- Xchar *
- Xhfgets(buf, len, fp)
- Xchar *buf;
- Xint len;
- XFILE *fp;
- X{
- X register int c;
- X register char *cp, *tp;
- X
- X if ((cp = fgets(buf, len, fp)) == NIL(char))
- X return NIL(char);
- X
- X if (*cp == '\n')
- X return cp;
- X
- X tp = cp + strlen(cp);
- X if (tp[-1] != '\n') {
- X /* Line too long - part read didn't fit into a newline */
- X while ((c = getc(fp)) != '\n' && c != EOF)
- X ;
- X } else
- X *--tp = '\0'; /* clobber newline */
- X
- X while ((c = getc(fp)) == ' ' || c == '\t') {
- X /* Continuation line. */
- X while ((c = getc(fp)) == ' ' || c == '\t')
- X ;
- X if (tp - cp < len) {
- X *tp++ = ' ';
- X *tp++ = c;
- X }
- X while ((c = getc(fp)) != '\n' && c != EOF)
- X if (tp - cp < len)
- X *tp++ = c;
- X }
- X *tp++ = '\n';
- X *tp++ = '\0';
- X if (c != EOF)
- X ungetc(c, fp); /* push back first char of next header */
- X return cp;
- X}
- X
- X
- X/*
- X * time to ascii
- X * leave time in static var
- X */
- Xchar *
- Xttoa(t)
- Xlong t;
- X{
- X static char buf[40];
- X struct tm *tp;
- X extern struct tm *localtime();
- X
- X tp = localtime(&t);
- X sprintf(buf, "%s, %d %s %d %02d:%02d:%02d %s", weekdays[tp->tm_wday],
- X tp->tm_mday, months[tp->tm_mon], tp->tm_year, tp->tm_hour, tp->tm_min,
- X tp->tm_sec, tzone);
- X return buf;
- X
- X}
- X
- X
- X/*
- X * ascii to time
- X * return 0L on error
- X */
- Xlong
- Xatot(s)
- Xchar *s;
- X{
- X char *argv[4];
- X int day, year, hour, min, sec;
- X char month[10], sday[10], stime[10], syear[10];
- X extern long maketime();
- X
- X if (sscanf(s, "%*s %d %*[ -] %9[^ -] %*[ -] %d %2d:%2d:%2d", &day, month,
- X &year, &hour, &min, &sec) != 6)
- X return 0L;
- X sprintf(sday, "%d", day);
- X sprintf(stime, "%d:%d:%d", hour, min, sec);
- X sprintf(syear, "%d", 1900 + year);
- X argv[0] = sday;
- X argv[1] = month;
- X argv[2] = stime;
- X argv[3] = syear;
- X return maketime(4, argv, STIMES);
- X}
- X
- X
- END_OF_FILE
- if test 10079 -ne `wc -c <'rna/header.c'`; then
- echo shar: \"'rna/header.c'\" unpacked with wrong size!
- fi
- # end of 'rna/header.c'
- fi
- if test -f 'rna/maketime.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'rna/maketime.c'\"
- else
- echo shar: Extracting \"'rna/maketime.c'\" \(8785 characters\)
- sed "s/^X//" >'rna/maketime.c' <<'END_OF_FILE'
- X/*
- X * long
- X * maketime(argc, argv, type)
- X *
- X * A standard routine to convert a future time (in English) to seconds.
- X * Arguments are order-independent (except for suffixes), and words
- X * may be shortened to a non-ambiguous abbreviation.
- X * As the time must be in the future, unspecified years, months and days default
- X * to the "next" year, month or day if necessary; otherwise the current
- X * month, day and hour are used.
- X *
- X * type is either TIMES in which days, times are recognised, or just DAYS.
- X *
- X * Tries hard to give meaningful messages, and make sure the user
- X * gets the time she/he wanted!
- X *
- X * Return is in seconds or 0 if error.
- X * Error messages to stderr.
- X *
- X * Michael Rourke (UNSW) Christmas 1982
- X *
- X * Syntax:
- X *
- X * timespec ::= { time | day | month | year } .
- X *
- X * time ::= [ hour [ ":" min [ ":" second ] ] ] [ timemodifier ] .
- X *
- X * timemodifier ::= "am" | "pm" | "noon" | "midday" | "midnight" | "now" .
- X *
- X * day ::= ( dayofweek [ "week" ] ) | number .
- X *
- X * dayofweek ::= "sunday" | "monday" | "tuesday" | "wednesday" |
- X * "thursday" | "friday" | "saturday" | "tomorrow" |
- X * "today" .
- X *
- X * month ::= "january" | "february" | "march" | "april" | "may" | "june" |
- X * "july" | "august" | "september" | "october" | "november" |
- X * "december" .
- X *
- X * year ::= "19" number .
- X *
- X */
- X
- X#include "defs.h"
- X
- X#define NOW -1
- X
- Xstatic timemod(), noonmid(), daymod(), weekday(), smonth();
- X
- Xstatic struct slist {
- X char *s_name;
- X int (*s_action)();
- X char s_val;
- X char s_type;
- X} slist[] =
- X{
- X { "am", timemod, 0, TIMES, },
- X { "pm", timemod, 12, TIMES, },
- X { "noon", noonmid, 12, TIMES, },
- X { "midday", noonmid, 12, TIMES, },
- X { "midnight", noonmid, 0, TIMES, },
- X { "now", noonmid, NOW, TIMES, },
- X { "week", daymod, 0, DAYS, },
- X { "sunday", weekday, 0, DAYS, },
- X { "monday", weekday, 1, DAYS, },
- X { "tuesday", weekday, 2, DAYS, },
- X { "wednesday", weekday, 3, DAYS, },
- X { "thursday", weekday, 4, DAYS, },
- X { "friday", weekday, 5, DAYS, },
- X { "saturday", weekday, 6, DAYS, },
- X { "tomorrow", weekday, 7, DAYS, },
- X { "today", weekday, 8, DAYS, },
- X { "january", smonth, 0, DAYS, },
- X { "february", smonth, 1, DAYS, },
- X { "march", smonth, 2, DAYS, },
- X { "april", smonth, 3, DAYS, },
- X { "may", smonth, 4, DAYS, },
- X { "june", smonth, 5, DAYS, },
- X { "july", smonth, 6, DAYS, },
- X { "august", smonth, 7, DAYS, },
- X { "september", smonth, 8, DAYS, },
- X { "october", smonth, 9, DAYS, },
- X { "november", smonth, 10, DAYS, },
- X { "december", smonth, 11, DAYS, },
- X { "", 0, 0, 0, }
- X};
- X
- X
- Xstatic char daysinmonth[12] =
- X{
- X 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
- X};
- X
- X
- Xstatic int hour, minute, second, day, year, dayofweek, month;
- Xstatic int settime, setday, setyear, setdayofweek, setmonth;
- Xstatic int setweek, err, setmod;
- Xstatic char *curarg;
- Xstatic struct tm *tim;
- Xstatic int gtype; /* global `type' arg */
- Xstatic short silent;
- X
- Xlong
- Xmaketime(argc, argv, type)
- Xint argc;
- Xchar **argv;
- Xint type;
- X{
- X struct tm *localtime();
- X long time(), construct(), now, then;
- X
- X if (type == STIMES)
- X type = TIMES, silent = 1;
- X else
- X silent = 0;
- X gtype = type;
- X now = time((long *) 0);
- X tim = localtime(&now);
- X
- X /*
- X * set defaults
- X */
- X hour = tim->tm_hour;
- X minute = tim->tm_min;
- X second = tim->tm_sec;
- X day = tim->tm_mday;
- X year = tim->tm_year + 1900;
- X dayofweek = tim->tm_wday;
- X month = tim->tm_mon;
- X
- X settime = setday = setyear = setdayofweek = setmonth = 0;
- X setweek = err = setmod = 0;
- X
- X while (argc--)
- X timearg(curarg = *argv++);
- X if (err)
- X return (long) 0;
- X
- X checktime();
- X if (err)
- X return (long) 0;
- X
- X then = construct();
- X /*
- X if(now > then)
- X {
- X error("Time specified has passed.");
- X return (long) 0;
- X }
- X*/
- X return then;
- X}
- X
- X
- Xstatic
- Xtimearg(s)
- Xchar *s;
- X{
- X lower(s);
- X if (isdigit(*s))
- X numbers(s);
- X else
- X words(s);
- X}
- X
- X
- Xstatic
- Xlower(s)
- Xregister char *s;
- X{
- X while (*s) {
- X *s = tolower(*s);
- X s++;
- X }
- X}
- X
- X
- Xstatic
- Xnumbers(s)
- Xregister char *s;
- X{
- X register int val;
- X
- X val = 0;
- X while (isdigit(*s))
- X val = val * 10 + *s++ - '0';
- X if (val > 1900)
- X if (setyear++)
- X reperror("year");
- X else
- X year = val;
- X else if (*s == '\0')
- X if (setday++)
- X reperror("day");
- X else
- X day = val;
- X else if (settime++)
- X reperror("time");
- X else
- X {
- X hour = val;
- X if (*s == ':') {
- X s++;
- X val = 0;
- X while (isdigit(*s))
- X val = val * 10 + *s++ - '0';
- X minute = val;
- X if (*s == ':') {
- X s++;
- X val = 0;
- X while (isdigit(*s))
- X val = val * 10 + *s++ - '0';
- X second = val;
- X } else
- X second = 0;
- X } else
- X minute = second = 0;
- X }
- X if (*s)
- X words(curarg = s);
- X}
- X
- X
- Xstatic
- Xreperror(s)
- Xchar *s;
- X{
- X error("Repeated %s argument: \"%s\"", s, curarg);
- X}
- X
- X
- X/* VARARGS1 */
- Xstatic
- Xerror(s, a1, a2, a3, a4)
- Xchar *s;
- Xint a1, a2, a3, a4;
- X{
- X err++;
- X if (silent)
- X return;
- X (void) fprintf(stderr, "Error in time specification: ");
- X (void) fprintf(stderr, s, a1, a2, a3, a4);
- X (void) fprintf(stderr, "\n");
- X}
- X
- X
- Xstatic
- Xwords(s)
- Xchar *s;
- X{
- X register struct slist *sp, *found;
- X register int size;
- X register char *wstart;
- X
- X sp = slist;
- X wstart = s;
- X size = 0;
- X while (*s && !isdigit(*s))
- X size++, s++;
- X found = (struct slist *) 0;
- X while (*(sp->s_name)) {
- X if (sp->s_type <= gtype && CMPN(sp->s_name, wstart, size) ==
- X 0)
- X if (!found) {
- X found = sp;
- X if (strlen(sp->s_name) == size)
- X break; /* otherwise an abbreviation */
- X }
- X else
- X {
- X error("Ambiguous abbreviation: \"%.*s\"", size,
- X wstart);
- X return;
- X }
- X sp++;
- X }
- X if (found)
- X (*(found->s_action))(found->s_val);
- X else
- X error("Unknown word: \"%.*s\"", size, wstart);
- X if (*s)
- X numbers(curarg = s);
- X}
- X
- X
- Xstatic
- Xtimemod(val)
- Xint val;
- X{
- X if (!settime)
- X error("Can only use \"am\" or \"pm\" after a time.");
- X else if (setmod++)
- X reperror("time modifier");
- X else if (hour < 12)
- X hour += val;
- X else if (hour > 12)
- X error("Can't use \"am\" or \"pm\" with 24 hour clock.");
- X else if (val == 0) /* am && hour == 12 */
- X hour = 0; /* 12am correction */
- X}
- X
- X
- Xstatic
- Xnoonmid(val)
- Xint val;
- X{
- X if (val < 0) /* NOW */ {
- X if (settime++)
- X reperror("time");
- X /* let defaults work */
- X } else if (setmod++) /* noon, midnight */
- X reperror("time modifier");
- X else
- X {
- X if (!settime)
- X settime++;
- X else if (hour != 12 || minute != 0 || second != 0)
- X error("Illegal time: %02d:%02d:%02d %s", hour, minute,
- X second, curarg);
- X hour = val;
- X minute = second = 0;
- X }
- X}
- X
- X
- Xstatic
- Xdaymod()
- X{
- X if (setweek++)
- X reperror("\b");
- X else if (!setdayofweek)
- X error("Can only use \"week\" after a weekday name.");
- X else
- X dayofweek += 7;
- X}
- X
- X
- Xstatic
- Xweekday(val)
- Xint val;
- X{
- X if (setday++)
- X reperror("day");
- X else
- X {
- X setdayofweek++;
- X if (val < 7) {
- X dayofweek = val - dayofweek; /* now a displacement */
- X if (dayofweek <= 0)
- X dayofweek += 7;
- X } else if (val == 7) /* tomorrow */
- X dayofweek = 1;
- X else /* today */
- X dayofweek = 0;
- X }
- X}
- X
- X
- Xstatic
- Xsmonth(val)
- Xint val;
- X{
- X if (setmonth++)
- X reperror("day of month");
- X else
- X month = val;
- X}
- X
- X
- Xstatic
- Xchecktime()
- X{
- X register int dim;
- X
- X if (gtype == DAYS && settime)
- X error("Times are not accepted.");
- X if (year < 1983 || year > 2038)
- X error("Year out of range.");
- X if (hour > 23 || minute > 59 || second > 59)
- X error("Illegal time: %02d:%02d:%02d", hour, minute, second);
- X if (!setdayofweek) {
- X dim = daysinmonth[month] + (month == 1 ? leapyear(year) : 0);
- X if (day > dim)
- X error("Month day out of range. (> %d)", dim);
- X }
- X if (setdayofweek && (setmonth || setyear))
- X error("Can't specify a weekday as well as a month or year.");
- X}
- X
- X
- Xstatic
- Xleapyear(y)
- Xint y;
- X{
- X return ((y % 4) == 0 && (y % 100) != 0) || (y % 400 == 0);
- X}
- X
- X
- Xstatic long
- Xconstruct()
- X{
- X register int i, days;
- X
- X adjust();
- X days = DAYSTO1983;
- X for (i = 1983; i < year; i++)
- X days += 365 + leapyear(i);
- X for (i = 0; i < month; i++)
- X days += daysinmonth[i] + (i == 1 ? leapyear(year) : 0);
- X days += day - 1; /* days since 1 Jan 1970 */
- X if (setdayofweek)
- X days += dayofweek;
- X return days * SECINDAY + hour * SECINHOUR + minute * SECINMIN + second;
- X}
- X
- X
- Xstatic
- Xadjust()
- X{
- X register int dim;
- X
- X /*
- X * make sure time defaults to the future
- X */
- X if (setdayofweek || setyear || month > tim->tm_mon)
- X return;
- X if (month < tim->tm_mon) {
- X year++;
- X return;
- X }
- X /*
- X * month == tim->tm_mon
- X */
- X if (day > tim->tm_mday)
- X return;
- X if (day < tim->tm_mday) {
- X if (setmonth || ++month / 12)
- X year++, month %= 12;
- X return;
- X }
- X /*
- X * month == tim->tm_mon && day == tim->tm_mday
- X */
- X if ((long)(hour*SECINHOUR + minute*SECINMIN + second) <
- X (long)(tim->tm_hour*SECINHOUR + tim->tm_min*SECINMIN + tim->tm_sec)) {
- X dim = daysinmonth[month] + (month == 1? leapyear(month): 0);
- X if (setday || ++day / dim) {
- X if (setmonth || ++month / 12)
- X year++, month %= 12;
- X day %= dim;
- X }
- X return;
- X }
- X}
- X
- X
- END_OF_FILE
- if test 8785 -ne `wc -c <'rna/maketime.c'`; then
- echo shar: \"'rna/maketime.c'\" unpacked with wrong size!
- fi
- # end of 'rna/maketime.c'
- fi
- if test -f 'rnews/relaynews.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'rnews/relaynews.c'\"
- else
- echo shar: Extracting \"'rnews/relaynews.c'\" \(9783 characters\)
- sed "s/^X//" >'rnews/relaynews.c' <<'END_OF_FILE'
- X/*
- X * relaynews - relay Usenet news (version C)
- X * See the file COPYRIGHT for the copyright notice.
- X *
- X * relaynews should be setuid-news, setgid-news. You'll need to install
- X * setnewsids setuid-root if setuid(geteuid()) doesn't work on your
- X * machine (e.g. on V7 and possibly SystemIII).
- X *
- X * Written by Geoff Collyer, 15-20 November 1985 and revised periodically
- X * since.
- X *
- X * relaynews parses Newsgroups: headers, rejects articles by newsgroup &
- X * message-id, files articles, updates the active & history files,
- X * transmits articles, and honours (infrequent) control messages, which do
- X * all sorts of varied and rococo things. Control messages are implemented
- X * by separate programs. relaynews reads a "sys" file to control the
- X * transmission of articles but can function as a promiscuous leaf node
- X * without one.
- X *
- X * A truly radical notion: people may over-ride via environment variables
- X * the compiled-in default directories so IHCC kludges are not needed and
- X * testing is possible (and encouraged) in alternate directories. This
- X * does cause a loss of privilege, to avoid spoofing.
- X *
- X * The disused I-have/send-me protocol is going to work; it's been broken
- X * in B news for ages but no one has noticed because it's essentially
- X * useless on the uucp network, especially when batching news articles,
- X * but NNTP may breathe new life into it.
- X *
- X * Portability vs SystemV. relaynews uses dbm(3) and makes no apologies
- X * for so doing. Imitation UNIX (registered trademark of AT&T in the
- X * United States) brand operating systems that lack dbm are going to
- X * have to use my incredibly slow dbm simulation.
- X */
- X
- X#include <stdio.h>
- X#include <ctype.h>
- X#include <errno.h>
- X#include <signal.h> /* to make locking safe */
- X#include <sys/types.h>
- X
- X#include "news.h"
- X#include "newspaths.h"
- X#include "active.h"
- X#include "cpu.h"
- X#include "headers.h"
- X#include "system.h"
- X
- X/*
- X * setuid-root program to set ids to news/news & rexec rnews with
- X * NEWSPERMS in the environment to break loops.
- X */
- X#ifndef SETNEWSIDS
- X#define SETNEWSIDS "setnewsids"
- X#endif
- X
- X#ifndef NEWSUSER
- X#define NEWSUSER "news"
- X#endif
- X#ifndef NEWSGROUP
- X#define NEWSGROUP "news"
- X#endif
- X
- Xchar *progname;
- X
- Xint remote = NO; /* articles are being relayed? */
- X
- Xchar *exclude = NULL; /* site to exclude, for erik */
- Xstatic int userealids = NO;
- X
- X/*
- X * main - parse arguments and handle options, lock & unlock news system.
- X */
- Xmain(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X int c, errflg = 0;
- X int status = ST_OKAY;
- X char origdir[MAXFILE]; /* current directory at start */
- X char *newpath;
- X extern int optind;
- X extern char *optarg;
- X
- X progname = argv[0];
- X
- X /* setuid daemon prelude; various precautions */
- X (void) umask(newsumask()); /* undo silly umasks */
- X (void) alarm(0); /* cancel any pending alarm */
- X /*
- X * Reset certain environment variables to sane values.
- X */
- X newpath = malloc(STRLEN("PATH=") + STRLEN(STDPATH) + 1);
- X if (newpath == NULL)
- X exit(1); /* no chatter until stdfdopen */
- X (void) strcpy(newpath, "PATH=");
- X (void) strcat(newpath, STDPATH);
- X if (!putenv(newpath) ||
- X !putenv("IFS= \t\n"))
- X exit(1); /* no chatter until stdfdopen */
- X closeall(1); /* closes all but std descriptors */
- X stdfdopen(); /* ensure standard descriptors are open */
- X
- X setids(argv); /* change of real and effective ids */
- X /* we are now running as news, so you can all relax */
- X
- X /* ignore signals (for locking). relaynews runs quickly, so don't worry. */
- X (void) signal(SIGINT, (sigarg_t)SIG_IGN);
- X (void) signal(SIGQUIT, (sigarg_t)SIG_IGN);
- X (void) signal(SIGHUP, (sigarg_t)SIG_IGN);
- X (void) signal(SIGTERM, (sigarg_t)SIG_IGN);
- X
- X /* parse options & set flags */
- X while ((c = getopt(argc, argv, "pd:x:")) != EOF)
- X switch (c) {
- X case 'p': /* "rnews" mode: */
- X ++remote; /* just relay, don't fuck about */
- X break;
- X /* all options below are new in C news */
- X case 'd': /* -d debug-options; thanks, henry */
- X if (!debugon(optarg))
- X errflg++; /* debugon already complained */
- X break;
- X case 'x': /* -x site: don't send to site */
- X /* you're welcome, erik */
- X if (exclude != NULL) {
- X (void) fprintf(stderr,
- X "%s: more than one -x site (%s)\n",
- X progname, optarg);
- X errflg++;
- X } else
- X exclude = optarg;
- X break;
- X default:
- X errflg++;
- X break;
- X }
- X if (errflg) {
- X (void) fprintf(stderr, "usage: %s [-p][-d fhlmt][-x site]\n",
- X progname);
- X exit(2);
- X }
- X
- X /* lock the news system, set up log files */
- X newslock(); /* done here due to dbm internal cacheing */
- X if (remote) { /* TODO: test this some other way */
- X redirectlogs(); /* rnews daemon: redirect to logs */
- X#ifdef MANYERRORS
- X (void) putc('\n', stderr); /* leave a blank line */
- X /* prints "Jun 5 12:34:56" */
- X timestamp(stderr, (time_t *)NULL, (char **)NULL);
- X (void) putc('\n', stderr);
- X#endif
- X }
- X
- X /* process file name arguments */
- X#ifdef RELATIVE_FILES_ALLOWED
- X if (getwd(origdir) == 0)
- X#endif
- X (void) strncpy(origdir, "/dunno/man/like/somewhere.", MAXFILE);
- X cd(fullartfile((char *)NULL)); /* move to spool directory */
- X
- X if (optind == argc)
- X status |= process(stdin, "stdin");
- X else
- X for (; optind < argc; optind++)
- X status |= relnmprocess(argv[optind], origdir);
- X
- X trclose(); /* close open batch files */
- X status |= synccaches(); /* just being cautious */
- X newsunlock(); /* unlock the news system */
- X exit(status);
- X}
- X
- Xsetids(argv) /* change of real and effective ids */
- Xchar **argv;
- X{
- X int newsuid = getuid(), newsgid = getgid(); /* default to real ids */
- X
- X (void) ctlfile((char *)NULL); /* trigger unprivileged(), set userealids */
- X if (!userealids) {
- X /*
- X * If setuid(geteuid()) fails, try execing a small,
- X * setuid-root program to just do getpwnam(), getgrnam()
- X * (with NEWSPERMS set), setgid(), setuid(),
- X * and exec this program again. If NEWSPERMS is set,
- X * the failure is a fatal error (recursive loop).
- X * Then this program can be setuid-news.
- X */
- X (void) setgid(getegid());
- X if (setuid(geteuid()) < 0) {
- X if (getenv("NEWSPERMS") != 0)
- X error("recursive loop setting ids", "");
- X execv(libfile(SETNEWSIDS), argv);
- X error("can't exec %s to set ids", libfile(SETNEWSIDS));
- X /* NOTREACHED */
- X }
- X /* you can relax, we are now running as news */
- X } else {
- X (void) setgid(newsgid);
- X (void) setuid(newsuid);
- X }
- X /* we are now running as news, so you can all relax */
- X}
- X
- Xvoid
- Xunprivileged() /* called if NEWSARTS, NEWSCTL or NEWSBIN present */
- X{
- X userealids = YES;
- X}
- X
- Xint /* YES/NO */
- Xdebugon(dbopt)
- Xregister char *dbopt;
- X{
- X int status = YES;
- X
- X for (; *dbopt != '\0'; dbopt++)
- X switch (*dbopt) {
- X case 'f':
- X filedebug(YES);
- X break;
- X case 'h':
- X hdrdebug(YES);
- X break;
- X case 'l':
- X lockdebug(YES);
- X break;
- X case 'm':
- X matchdebug(YES);
- X break;
- X case 't':
- X transdebug(YES);
- X break;
- X default:
- X status = NO; /* unknown debugging option */
- X (void) fprintf(stderr, "%s: bad -d %c\n",
- X progname, *dbopt);
- X break;
- X }
- X return status;
- X}
- X
- X/*
- X * Redirect stdout and stderr into log files at known locations.
- X */
- Xredirectlogs()
- X{
- X logfile(stdout, libfile("log"));
- X logfile(stderr, libfile("errlog"));
- X}
- X
- Xlogfile(stream, name) /* redirect stream into name */
- XFILE *stream;
- Xchar *name;
- X{
- X if (freopen(name, "a", stream) == NULL)
- X errunlock("can't redirect standard stream to %s", name);
- X}
- X
- Xint /* status */
- Xrelnmprocess(name, origdir) /* process a (relative) file name */
- Xchar *name, *origdir;
- X{
- X register int status = ST_OKAY;
- X register FILE *in;
- X register char *fullname;
- X
- X fullname = emalloc((unsigned)strlen(origdir) + STRLEN(SFNDELIM) +
- X strlen(name) + 1);
- X fullname[0] = '\0';
- X
- X if (name[0] != FNDELIM) { /* relative path */
- X (void) strcat(fullname, origdir);
- X (void) strcat(fullname, SFNDELIM);
- X }
- X (void) strcat(fullname, name);
- X
- X in = fopen(fullname, "r");
- X if (in == NULL)
- X warning("can't open argument `%s'", fullname);
- X else {
- X status |= process(in, fullname);
- X (void) fclose(in);
- X }
- X free(fullname);
- X return status;
- X}
- X
- X/*
- X * process - process input file
- X * If it starts with '#', assume it's a batch and unravel it,
- X * else it's a single article, so just inject it.
- X */
- Xint
- Xprocess(in, inname)
- XFILE *in;
- Xchar *inname;
- X{
- X register int c;
- X
- X if ((c = getc(in)) == EOF)
- X return ST_OKAY; /* normal EOF */
- X (void) ungetc(c, in);
- X if (c == '#')
- X return unbatch(in, inname);
- X else
- X /* ST_SHORT should always come on with a count of MAXLONG */
- X return cpinsart(in, inname, MAXLONG) & ~ST_SHORT;
- X}
- X
- X/*
- X * Unwind in and insert each article.
- X * For each article, call cpinsart to copy the article
- X * from in into a temporary file and rename the temp file
- X * into the news spool directory.
- X */
- Xint
- Xunbatch(in, inname)
- XFILE *in;
- Xchar *inname;
- X{
- X register int c;
- X long charcnt;
- X int status = ST_OKAY;
- X char line[MAXLINE];
- X
- X while (!(status&ST_DISKFULL) && (c = getc(in)) != EOF) {
- X (void) ungetc(c, in);
- X /*
- X * While out of sync, eat input lines,
- X * then eat the tail end of the "#! rnews" line.
- X */
- X while (fgets(line, sizeof line, in) != NULL &&
- X !batchln(line, &charcnt)) {
- X status |= ST_DROPPED; /* argh! a bad batch */
- X (void) fprintf(stderr, "%s: unbatcher out of synch, tossing: ",
- X progname);
- X (void) fputs(line, stderr);
- X }
- X if (!feof(in))
- X status |= cpinsart(in, inname, charcnt);
- X }
- X return status;
- X}
- X
- X/*
- X * Is line a batcher-produced line (#! rnews count)?
- X * If so, return the count through charcntp.
- X * This is slightly less convenient than sscanf, but a lot smaller.
- X */
- Xint /* YES/NO */
- Xbatchln(line, charcntp)
- Xregister char *line;
- Xregister long *charcntp;
- X{
- X register char *countp;
- X static char batchtext[] = "#! rnews ";
- X
- X countp = line + STRLEN(batchtext);
- X if (STREQN(line, batchtext, STRLEN(batchtext)) &&
- X isascii(*countp) && isdigit(*countp)) {
- X *charcntp = atol(countp);
- X return YES;
- X } else {
- X *charcntp = 0;
- X return NO;
- X }
- X}
- END_OF_FILE
- if test 9783 -ne `wc -c <'rnews/relaynews.c'`; then
- echo shar: \"'rnews/relaynews.c'\" unpacked with wrong size!
- fi
- # end of 'rnews/relaynews.c'
- fi
- if test -f 'rnews/transmit.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'rnews/transmit.c'\"
- else
- echo shar: Extracting \"'rnews/transmit.c'\" \(7923 characters\)
- sed "s/^X//" >'rnews/transmit.c' <<'END_OF_FILE'
- X/*
- X * transmit - transmit incoming articles to neighbouring machines
- X * TODO: deal with multiple references to the same batch file.
- X */
- X
- X#include <stdio.h>
- X#include <ctype.h>
- X#include <sys/types.h>
- X#include "news.h"
- X#include "newspaths.h"
- X#include "headers.h"
- X#include "system.h"
- X
- X#define NOPENTFS 10 /* # of file descriptors kept open for batching */
- X
- Xstatic FILE *tfs[NOPENTFS]; /* keep these open always */
- Xstatic int debug = NO;
- X
- Xtransdebug(state)
- Xint state;
- X{
- X debug = state;
- X}
- X
- X/*
- X * For each system in "sys" other than this one,
- X * transmit this article when its ng pattern matches
- X * hdrs->h_distr (which may be just a copy of hdrs->h_ngs).
- X */
- Xint
- Xtransmit(hdrs, rmt, exclude)
- Xregister struct headers *hdrs;
- Xint rmt; /* inews/rnews flag */
- Xchar *exclude; /* no copy to him */
- X{
- X register struct system *sys;
- X register int fno = 0;
- X int status = 0;
- X
- X rewsys();
- X if (debug)
- X (void) fprintf(stderr, "just rewound sys file\n");
- X while ((sys = nextsys()) != NULL) {
- X if (debug) {
- X (void) fprintf(stderr, "hdrs->h_distr=%s\n",
- X hdrs->h_distr);
- X (void) fprintf(stderr, "sy_name=%s sy_ngs=%s\n",
- X sys->sy_name, sys->sy_ngs);
- X }
- X if (oktransmit(hdrs, sys, sys->sy_flags, rmt, exclude))
- X status |= ejaculate(hdrs, sys, fno);
- X if (sys->sy_flags&(FLG_BATCH|FLG_SZBATCH))
- X ++fno; /* count lines with F or f flag */
- X }
- X if (debug)
- X (void) fprintf(stderr, "just finished reading sys file\n");
- X return status;
- X}
- X
- X/*
- X * Is it okay to send the article corresponding to hdrs to sys,
- X * given flags (derived from sys) and rmt?
- X *
- X * Never send to this host, nor any host named in Path:.
- X * Newsgroups must match sys's subscription list.
- X * Also, Distribution: must match sys's distribution list.
- X * If L flag is on, must be a local posting.
- X *
- X * TODO: implement Ln restriction:
- X * forward articles generated within sysp->sy_lochops hops of here.
- X * TODO: implement exclusions by site, from sy_excl (can be NULL).
- X */
- Xstatic int
- Xoktransmit(hdrs, sys, flags, rmt, exclude)
- Xregister struct headers *hdrs;
- Xregister struct system *sys;
- Xint flags, rmt;
- Xchar *exclude; /* no copy to him */
- X{
- X return (!(flags&FLG_LOCAL) || !rmt) && /* local & */
- X !STREQ(hostname(), sys->sy_name) && /* not to ME & */
- X (exclude == NULL || !STREQ(exclude, sys->sy_name)) && /* not excluded & */
- X (hdrs->h_path == NULL || !hostin(hdrs->h_path, sys->sy_name)) && /* not been here & */
- X ngmatch(sys->sy_ngs, hdrs->h_ngs) && /* ngs match & */
- X /* RFC 850 is wrong, yea, verily: Distribution:s are *not* patterns */
- X ngmatch(sys->sy_distr, hdrs->h_distr); /* distrs match! */
- X}
- X
- X/*
- X * send the article denoted by hdrs to the system denoted by sys.
- X */
- XSTATIC int /* status */
- Xejaculate(hdrs, sys, fno) /* kick the article to its reward */
- Xregister struct headers *hdrs;
- Xregister struct system *sys;
- Xint fno;
- X{
- X int status = ST_OKAY;
- X char filename[MAXLINE];
- X char *fullname;
- X
- X /* can't use hdrs->h_tmpf because we need a permanent name */
- X first(hdrs->h_files, filename);
- X mkfilenm(filename);
- X (void) printf(" %s", sys->sy_name); /* logging */
- X if (debug)
- X (void) fprintf(stderr, "transmitting %s to %s\n",
- X hdrs->h_msgid, sys->sy_name);
- X
- X /* must supply a full pathname to the outside world */
- X fullname = fullspoolfile(filename);
- X if (sys->sy_flags&(FLG_BATCH|FLG_SZBATCH))
- X status |= trbatch(sys, hdrs, fullname, fno);
- X else
- X status |= trcmd(sys, fullname);
- X return status;
- X}
- X
- X/*
- X * Append filename to sys->sy_cmd. fno is the ordinal number of this sys line.
- X * If fno is low enough, use the tfs cache of batch file descriptors.
- X */
- Xint
- Xtrbatch(sys, hdrs, filename, fno)
- Xstruct system *sys;
- Xstruct headers *hdrs;
- Xchar *filename;
- Xregister int fno;
- X{
- X register int status = 0;
- X char *batfile = sys->sy_cmd;
- X
- X if (fno >= NOPENTFS) { /* not cachable */
- X register FILE *batchf = fopenclex(batfile, "a");
- X
- X if (batchf == NULL) {
- X warning("can't open batch file %s", batfile);
- X status |= ST_DROPPED;
- X } else {
- X status |= trappend(batchf, sys, hdrs, filename);
- X if (fclose(batchf) == EOF)
- X status = fulldisk(status|ST_DROPPED, batfile);
- X }
- X } else { /* cachable */
- X if (tfs[fno] == NULL) { /* closed */
- X tfs[fno] = fopenclex(batfile, "a");
- X if (tfs[fno] == NULL) { /* didn't open */
- X register int openf;
- X
- X /*
- X * Assume open failed due to lack of file
- X * descriptors. Find an open one and close it,
- X * then retry the open. Honk at someone too?
- X */
- X for (openf = 0; openf < NOPENTFS; openf++)
- X if (tfs[openf] != NULL) /* open */
- X break;
- X if (openf < NOPENTFS && tfs[openf] != NULL) {
- X if (fclose(tfs[openf]) == EOF)
- X status = fulldisk(status|ST_DROPPED,
- X "some batch file");
- X tfs[openf] = NULL; /* mark closed */
- X tfs[fno] = fopenclex(batfile, "a");
- X }
- X }
- X }
- X if (tfs[fno] == NULL) { /* still closed! */
- X warning("can't open batch file %s", batfile);
- X status |= ST_DROPPED;
- X } else
- X status |= trappend(tfs[fno], sys, hdrs, filename);
- X }
- X return status;
- X}
- X
- Xstatic int
- Xtrappend(fp, sys, hdrs, name) /* write name\n on fp */
- Xregister FILE *fp;
- Xregister struct system *sys;
- Xregister struct headers *hdrs;
- Xchar *name;
- X{
- X int status = ST_OKAY;
- X
- X if (fputs(name, fp) == EOF) /* append to batch file */
- X status = fulldisk(status|ST_DROPPED, "some batch file");
- X /* for Henry's new batcher */
- X if (sys->sy_flags&FLG_SZBATCH &&
- X fprintf(fp, " %ld", hdrs->h_charswritten) == EOF)
- X status = fulldisk(status|ST_DROPPED, "some batch file");
- X /* don't check putc return value for portability; use ferror */
- X (void) putc('\n', fp);
- X (void) fflush(fp); /* for crash-proofness */
- X if (ferror(fp))
- X status = fulldisk(status|ST_DROPPED, "some batch file");
- X return status;
- X}
- X
- X/*
- X * Execute sys->sy_cmd with the current article as stdin
- X * and filename substituted for %s in sys->sy_cmd (if any).
- X */
- Xint
- Xtrcmd(sys, filename)
- Xstruct system *sys;
- Xchar *filename;
- X{
- X int status = ST_OKAY, exitstat;
- X char *cmd;
- X char *syscmd = sys->sy_cmd;
- X
- X cmd = emalloc((unsigned)STRLEN("PATH=") + STRLEN(STDPATH) + STRLEN(" <") +
- X strlen(filename) + STRLEN(" ") + strlen(syscmd) +
- X strlen(filename) + 1);
- X (void) strcpy(cmd, "PATH=");
- X (void) strcat(cmd, STDPATH);
- X (void) strcat(cmd, " <");
- X /*
- X * redirect stdin to prevent consuming my stdin & so cmd's stdin
- X * is filename by default.
- X */
- X (void) strcat(cmd, filename);
- X (void) strcat(cmd, " ");
- X (void) sprintf(cmd+strlen(cmd), syscmd, filename);
- X exitstat = system(cmd);
- X if (exitstat != 0) {
- X extern char *progname;
- X
- X status |= ST_DROPPED;
- X (void) fprintf(stderr, "%s: `%s' returned exit status 0%o\n",
- X progname, cmd, exitstat);
- X }
- X free(cmd);
- X return status;
- X}
- X
- Xtrclose()
- X{
- X register int fno;
- X
- X for (fno = 0; fno < NOPENTFS; fno++)
- X if (tfs[fno] != NULL) {
- X (void) fclose(tfs[fno]);
- X tfs[fno] = NULL;
- X }
- X}
- X
- X/*
- X * Return true iff host appears in s, with no characters from the alphabet
- X * of legal hostname characters immediately adjacent.
- X * This function is a profiling hot spot, so it has been optimised.
- X */
- Xint
- Xhostin(s, host)
- Xregister char *s, *host;
- X{
- X register int hostlen = strlen(host);
- X register int ch; /* use by hostchar macro */
- X
- X/* If c is NUL, hostchar will be false, so don't test (optimisation: ==). */
- X#define nothostchar(c) (!hostchar(c) /* || (c) == '\0' */ ) /* ! or EOS */
- X/*
- X * True if c can be part of a hostname. RFC 850 allows letters, digits, periods,
- X * and hyphens and specifically disallows blanks. False may mean c is NUL.
- X */
- X#define hostchar(c) (ch = (c) , \
- X (isascii(ch) && (isalnum(ch) || (ch) == '.' || (ch) == '-')))
- X
- X /*
- X * Special case: match host!path or host.
- X */
- X if (STREQN(s, host, hostlen) && nothostchar(s[hostlen]))
- X return YES;
- X /*
- X * Match path2!host!path or path2!host.
- X */
- X while (*s != '\0')
- X if (hostchar(s[0])) /* can't start after here */
- X ++s;
- X else if ((++s, STREQN(s, host, hostlen)) &&
- X nothostchar(s[hostlen]))
- X return YES;
- X return NO;
- X}
- END_OF_FILE
- if test 7923 -ne `wc -c <'rnews/transmit.c'`; then
- echo shar: \"'rnews/transmit.c'\" unpacked with wrong size!
- fi
- # end of 'rnews/transmit.c'
- fi
- echo shar: End of archive 10 \(of 14\).
- ## End of shell archive.
- exit 0
-